package zone.czh.woi.woim.protocol.dectector;

import zone.czh.woi.woim.server.channel.protocol.detector.ProtocolDetector;
import zone.czh.woi.woim.server.channel.protocol.initializer.ProtocolInitializer;

import java.util.Arrays;

/**
*@ClassName: DefaultProxyProtocolV1Detector
*@Description: None
*@author woi
*/
public class DefaultProxyProtocolV1Detector extends ProtocolDetector {

    public static final int PARSING_PROTOCOL_PROXY = 0;
    public static final int FINISH_PROTOCOL_PROXY = 1;
    public static final String KEY_PROGRESS = "progress";


    public DefaultProxyProtocolV1Detector(){
        super(5);
    }

    @Override
    public ProtocolInitializer.Intent detect(byte[] bytes, ProtocolInitializer.Intent latestIntent) {
        if (latestIntent==null){
            latestIntent = new ProtocolInitializer.Intent();
            latestIntent.getExtras().put(KEY_PROGRESS,PARSING_PROTOCOL_PROXY);
            latestIntent.setDetectRange(bytes.length);
        }

        if (latestIntent.getExtras().get(KEY_PROGRESS).equals(PARSING_PROTOCOL_PROXY)){
            if (new String(Arrays.copyOf(bytes,5)).equals("PROXY")){
                if (bytes[bytes.length-1]!=10){
                    latestIntent.setDetectRange(bytes.length+1);
                }else {
                    String proxyProtocol = new String(bytes);
                    String[] fragment = proxyProtocol.split(" ");
                    if (fragment.length>2){
                        latestIntent.setProxy(true);
                        latestIntent.setRealRemoteIp(fragment[2]);
                        latestIntent.getExtras().put(KEY_PROGRESS,FINISH_PROTOCOL_PROXY);
                        latestIntent.setResetReaderIndex(false);
                        latestIntent.setRealRemoteIp(fragment[2]);
                        latestIntent.setRealRemotePort(Integer.parseInt(fragment[4]));
                    }

                }
            }else {
                latestIntent.getExtras().put(KEY_PROGRESS,FINISH_PROTOCOL_PROXY);
                latestIntent.setDetectRange(2);
                latestIntent.setProxy(false);
                latestIntent.setResetReaderIndex(true);
                latestIntent.setFinished(false);
            }
        }else {
            if (isHttp(bytes[0],bytes[1])){
                latestIntent.setProtocolName("web_socket");
            }else {
                latestIntent.setProtocolName("protobuf");
            }
            latestIntent.setResetReaderIndex(true);
            latestIntent.setFinished(true);
        }


        return latestIntent;
    }

    private boolean isHttp(int magic1, int magic2) {
        return magic1 == 'G' && magic2 == 'E' || // GET
                magic1 == 'P' && magic2 == 'O' || // POST
                magic1 == 'P' && magic2 == 'U' || // PUT
                magic1 == 'H' && magic2 == 'E' || // HEAD
                magic1 == 'O' && magic2 == 'P' || // OPTIONS
                magic1 == 'P' && magic2 == 'A' || // PATCH
                magic1 == 'D' && magic2 == 'E' || // DELETE
                magic1 == 'T' && magic2 == 'R' || // TRACE
                magic1 == 'C' && magic2 == 'O';   // CONNECT
    }
}
